#include "app_bt.h"

/**
 * 等待蓝牙模块的确认
 */
static int wait_ack(Device *device)
{
    // 注意：需要等待一定时间，因为蓝牙模块需要一定时间来处理指令
    usleep(1000 * 100); // 50ms

    // 从设备中读取4个字节的数据
    char buf[4];
    read(device->fd, buf, 4);
    // 如果读取的数据是“OK\r\n”则代表成功，返回0, 否则返回-1
    if (memcmp(buf, "OK\r\n", 4) == 0)
    {
        return 0;
    }
    return -1;
}

/**
 * 初始化蓝牙连接
 */
static int init_bt(Device *device)
{
    // 初始串口 9600 / 阻塞
    app_serial_init(device);

    // 设置串口为非阻塞模式
    app_serial_setBlock(device, 0);
    tcflush(device->fd, TCIOFLUSH);

    // 判断蓝牙可用才去设置蓝牙属性
    if (app_bt_status(device) == 0)
    {
        printf("蓝牙波特率为9600...\n");
        // // 修改蓝牙波特率
        // int result = app_bt_setBraudRate(device, BT_BAUD_115200);
        // if (result != 0)
        // {
        //     printf("蓝牙波特率设置失败...\n");
        // }

        // // 重置
        // result = app_bt_reset(device);
        // if (result != 0)
        // {
        //     printf("蓝牙重启失败...\n");
        // }
        // sleep(2); // 等待蓝牙复位
    }

    // 将串口的波特率修改为115200
    // app_serial_setBraudRate(device, BR_115200);
    // tcflush(device->fd, TCIOFLUSH);

    // 设置蓝牙的Netid/MADDR/Name
    int result = app_bt_rename(device, "atguigu");
    if (result != 0)
    {
        printf("蓝牙更名失败...\n");
    }
    result = app_bt_setNetId(device, "1234");
    if (result != 0)
    {
        printf("蓝牙设置组网ID失败...\n");
    }
    result = app_bt_setmaddr(device, "0001");
    if (result != 0)
    {
        printf("蓝牙设置地址失败...\n");
    }

    // 判断蓝牙是否可用， 如果不可用则返回-1
    if (app_bt_status(device) != 0)
    {
        log_error("蓝牙初始化失败");
        return -1;
    }

    // 将串口改为阻塞模式
    app_serial_setBlock(device, 1);
    tcflush(device->fd, TCIOFLUSH);

    log_debug("蓝牙初始化成功");
    return 0;
}

/**
 * 初始化
 * 1.将蓝牙数据的预处理方法装配给设备模块
 * 2.设置设备的蓝牙默认配置，并连接蓝牙
 */
int app_bt_init(Device *device)
{
    device->pre_write = app_bt_preWrite;
    device->post_read = app_bt_postRead;

    init_bt(device);

    return 0;
}

/**
 * 写前预处理
 * @param data 01 02 04 58 58 61 62 63 64
 * @param len  9
 * 处理后:41 54 2b 4d 45 53 48 00 ff ff 61 62 63 64 0d 0a
 * AT+MESH 0xFF 0xFF abcd \r\n
 */
int app_bt_preWrite(char *data, int len)
{
    // 创建一个临时数组用于存放处理后的数据
    char data_buffer[256];

    // 拼接AT指令的头
    memcpy(data_buffer, "AT+MESH", 8);

    // 拼接ID
    memcpy(&data_buffer[8], &data[3], 2);

    // 拼接数据
    memcpy(&data_buffer[10], &data[5], len - 5);

    // 拼接\r\n
    memcpy(&data_buffer[len + 5], "\r\n", 2);

    // 先清空data数据
    memset(data, 0, sizeof(data));

    // 将临时缓存数据拷贝回原数组
    memcpy(data, data_buffer, len + 7);

    // 返回新数组数据长度
    return len + 7;
}

static char data_buffer[256];
static int data_len = 0;
static char fix_header[2] = {0xF1, 0xDD};

/**
 *  读后预处理
 */
int app_bt_postRead(char *data, int len)
{
    // 将当次读取到的数据放入全局变量
    memcpy(&data_buffer[data_len], data, len);
    data_len += len;

    // 不满足最小数据长度,说明数据不完整,直接返回,等待下一次统一处理
    if (data_len < 8)
    {
        log_info("数据不完整,等待下一次统一处理...");
        return 0;
    }

    // 遍历数组,匹配目标数据:指的是以"F1,DD"开头
    int i;
    for (i = 0; i < data_len - 7; i++)
    {
        // 匹配目标数据:以"F1,DD"开头
        // if (memcmp(&data_buffer[i], fix_header, 2) == 0)
        // log_error("当前数据 = %#x", data_buffer[i]);
        if (memcmp(data_buffer + i, fix_header, 2) == 0)
        {
            // 匹配上了,则删除前面所有数据
            data_len -= i;
            memmove(data_buffer, &data_buffer[i], data_len);
            log_info("匹配上了,则删除前面所有数据...%.*s", data_len, data_buffer);

            // 查看本次下游设备发送的数据总长度
            int cur_len = data_buffer[2] + 3;
            log_info("当次数据长度为%d,蓝牙数据长度为%d", data_len, cur_len);
            if (cur_len > data_len)
            {
                // 当前全部变量中保存的数据不全,等待下一次一起处理
                log_info("当前全部变量中保存的数据不全,等待下一次一起处理...");
                return 0;
            }
            else
            {
                // 当前全部变量中保存的数据足够,给到外面写入缓冲区
                memset(data, 0, sizeof(data));

                data[0] = 1;           // conn_type
                data[1] = 2;           // id_len
                data[2] = cur_len - 7; // msg_len

                // data_buffer:f1 dd 07 23 23 FF FF msg
                memcpy(&data[3], &data_buffer[3], 2);           // id
                memcpy(&data[5], &data_buffer[7], cur_len - 7); // msg
                log_info("匹配上头数据,且数据长度足够...");

                // 将拷贝出去的有效数据在全局缓冲区中删除
                data_len = data_len - cur_len;
                log_info("处理以后数据长度为%d", data_len);
                memmove(data_buffer, &data_buffer[cur_len + i], data_len);

                // 01 02 03 23 23 41 42 43
                return cur_len - 2;
            }
        }
    }

    // 循环结束都没有匹配上,删除数据,等待下一次数据一起处理
    memmove(data_buffer, &data_buffer[data_len - 7], 7);
    data_len = 7;

    return 0;
}

/**
 * 测试蓝牙是否可用
 */
int app_bt_status(Device *device)
{
    // 向串口发送测试指令 也就是写入“AT\r\n”
    write(device->fd, "AT\r\n", 4);
    // 返回是否成功/确认的结果
    return wait_ack(device);
}

/**
 * 修改蓝牙名称
 */
int app_bt_rename(Device *device, char *name)
{
    char cmd[100];
    sprintf(cmd, "AT+NAME%s\r\n", name);
    write(device->fd, cmd, strlen(cmd));

    return wait_ack(device);
}

/**
 * 设置波特率
 */
int app_bt_setBraudRate(Device *device, BTBraudRate baud_rate)
{
    char cmd[100];
    sprintf(cmd, "AT+BAUD%c\r\n", baud_rate);
    write(device->fd, cmd, strlen(cmd));

    return wait_ack(device);
}

/**
 * 重置(修改的配置才生效)
 */
int app_bt_reset(Device *device)
{
    write(device->fd, "AT+RESET\r\n", 10);

    return wait_ack(device);
}

/**
 * 设置组网id(同一个组的多个设备组网id相同)
 * net_id： 4位十六进制字符串
 */
int app_bt_setNetId(Device *device, char *net_id)
{
    char cmd[100];
    sprintf(cmd, "AT+NETID%s\r\n", net_id);
    write(device->fd, cmd, strlen(cmd));

    return wait_ack(device);
}

/**
 * 设置蓝牙MAC地址(同一个组的多个设备MAC地址不同)
 * maddr: 4位十六进制字符串
 */
int app_bt_setmaddr(Device *device, char *maddr)
{
    char cmd[100];
    sprintf(cmd, "AT+MADDR%s\r\n", maddr);
    write(device->fd, cmd, strlen(cmd));

    return wait_ack(device);
}
